#include "AbstractRemoteProcedure.h"
namespace TC
{
    namespace Request
    {

        AbstractRemoteProcedure::AbstractRemoteProcedure(QObject *parent /*= nullptr*/) : AbstractProcedure(parent)
        {

        }

        AbstractRemoteProcedure::~AbstractRemoteProcedure()
        {
            if (socket)
			{
				socket->deleteLater();
            }
            socket = nullptr;
        }

        void AbstractRemoteProcedure::get(const QString &command, const QVariantMap &args)
        {
            if (status() == Status::Communicating)
                throw std::runtime_error("New call to AbstractRemoteProcedure::get while communicating");
            socket = Network::Manager::instance()->get(command, args);

            QObject::connect(socket, static_cast<void(Connection::*)(const QString &)>(&Connection::error), this, &AbstractRemoteProcedure::setError);
            QObject::connect(socket, &Connection::readyRead, this, &AbstractRemoteProcedure::onSocketReadyRead);
            QObject::connect(socket, &Connection::disconnected, this, &AbstractRemoteProcedure::onSocketDisconnected);

            // auto-delete
            QObject::connect(socket, static_cast<void(Connection::*)(const QString &)>(&Connection::error), socket, &Connection::deleteLater);
            QObject::connect(socket, &Connection::disconnected, socket, &Connection::deleteLater);


            setCommunicationing();
        }

        void AbstractRemoteProcedure::terminate()
        {
            if (status() == Status::Communicating)
            {
                socket->disconnect(); // disconnect signals
				//socket->deleteLater(); // done by connection
                socket = nullptr;
                setReady();
            }
        }

        void AbstractRemoteProcedure::onSocketReadyRead()
        {
            auto data = socket->readAll();
            QDataStream stream(&data, QIODevice::ReadOnly);

            assert(status() == Status::Communicating);
            onDataReady(stream);
            assert(status() == Status::Ok || status() == Status::Failed);

			socket->disconnect(); // disconnect signals
			//socket->deleteLater(); // done by connection
            socket = nullptr;
        }

        void AbstractRemoteProcedure::onSocketDisconnected()
        {
            if (status() == Status::Communicating)
				setError("Remote closed the connection with no reason.");
			//socket->deleteLater(); // done by connection
            socket = nullptr;
        }
    }

}
